package aliyun

import (
	"encoding/json"

	"gitee.com/Luna-CY/Golang-Project-Template/internal/configuration"
	"gitee.com/Luna-CY/Golang-Project-Template/internal/context"
	"gitee.com/Luna-CY/Golang-Project-Template/internal/errors"
	"gitee.com/Luna-CY/Golang-Project-Template/internal/logger"
	"gitee.com/Luna-CY/Golang-Project-Template/internal/util/pointer"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	"github.com/alibabacloud-go/dysmsapi-20170525/v5/client"
)

func New(config configuration.SmsProvider) (*AliYun, errors.Error) {
	c, err := client.NewClient(&openapi.Config{AccessKeyId: &config.AliYun.AccessKey, AccessKeySecret: &config.AliYun.SecretKey})
	if nil != err {
		logger.SugarLogger(logger.WithStack()).Errorf("ISSPA_UN.N_EW.153736 创建短信提供商失败，错误信息为 %q", err.Error())

		return nil, errors.ErrorServerInternalError("ISSPA_UN.N_EW.173742", "创建短信提供商失败")
	}

	return &AliYun{
		config: config,
		client: c,
	}, nil
}

type AliYun struct {
	config configuration.SmsProvider
	client *client.Client
}

func (cls *AliYun) GetName() string {
	return cls.config.Name
}

func (cls *AliYun) Send(ctx context.Context, telephone string, templateCode string, templateParams map[string]string) errors.Error {
	var mapping map[string]string

	for _, code := range cls.config.TemplateCodes {
		if code.TemplateCode == templateCode {
			mapping = code.Params
		}
	}

	// 映射模板参数表
	var params = make(map[string]any)
	for k, v := range templateParams {
		if _, ok := mapping[k]; !ok {
			logger.SugarLogger(logger.WithRequestId(ctx), logger.WithStack()).Errorf("ISSPA_UN.AY_UN.S_ND.413806 未定义的模板参数映射，模板代码为 %s，参数名称为 %s", templateCode, k)

			return errors.ErrorServerInternalError("ISSPA_UN.AY_UN.S_ND.433838", "未定义的模板参数映射，模板代码为 %s，参数名称为 %s", templateCode, k)
		}

		params[mapping[k]] = v
	}

	bs, err := json.Marshal(params)
	if nil != err {
		logger.SugarLogger(logger.WithRequestId(ctx), logger.WithStack()).Errorf("ISSPA_UN.AY_UN.S_ND.534131 序列化模板参数失败，错误信息为 %q", err.Error())

		return errors.ErrorServerInternalError("ISSPA_UN.AY_UN.S_ND.554136", "序列化模板参数失败")
	}

	var request = &client.SendSmsRequest{
		PhoneNumbers:  pointer.New(telephone),
		SignName:      pointer.New(cls.config.AliYun.SignName),
		TemplateCode:  pointer.New(templateCode),
		TemplateParam: pointer.New(string(bs)),
	}

	response, err := cls.client.SendSms(request)
	if nil != err {
		logger.SugarLogger(logger.WithRequestId(ctx), logger.WithStack()).Errorf("ISSPA_UN.AY_UN.S_ND.684214 发送短信失败，错误信息为 %q", err.Error())

		return errors.ErrorServerInternalError("ISSPA_UN.AY_UN.S_ND.704222", "创建短信发送请求对象失败")
	}

	if 200 != *response.StatusCode || "OK" != *response.Body.Code {
		logger.SugarLogger(logger.WithRequestId(ctx), logger.WithStack()).Errorf("ISSPA_UN.AY_UN.S_ND.744258 发送短信失败，错误信息为 %q", *response.Body.Message)

		return errors.ErrorServerInternalError("ISSPA_UN.AY_UN.S_ND.764306", "发送短信失败")
	}

	return nil
}
